package gstyle;

import com.google.gwt.user.client.ui.Widget;
import gstyle.font.Font;
import gstyle.item.Unit;

import java.util.*;

public abstract class Style<T> {

    String name;
    private Map attributes = new HashMap();
    private List siblings = new ArrayList();
    private static final String WIDTH = "width";
    private static final String HEIGHT = "height";
    public static final String BACKGROUND_COLOR = "background-color";
    public static final String BACKGROUND_IMAGE = "background-image";
    public static final String BACKGROUND_POSITION = "background-position";
    public static final String BACKGROUND_REPEAT = "background-repeat";
    public static final String BORDER = "border";
    public static final String BORDER_TOP = "border-top";
    public static final String BORDER_RIGHT = "border-right";
    public static final String BORDER_BOTTOM = "border-bottom";
    public static final String BORDER_LEFT = "border-left";
    public static final String COLOR = "color";
    public static final String FONT_FAMILY = "font-family";
    public static final String FONT_SIZE = "font-size";
    public static final String FONT_WEIGHT = "font-weight";
    public static final String MARGIN = "margin";
    public static final String OVERFLOW = "overflow";
    public static final String PADDING = "padding";
    public static final String PADDING_TOP = "padding-top";
    public static final String PADDING_BOTTOM = "padding-bottom";
    public static final String PADDING_LEFT = "padding-left";
    public static final String PADDING_RIGHT = "padding-right";
    public static final String LINE_HEIGHT = "lineHeight";
    public static final String BACKGROUND = "background";
    public static final String BORDER_WIDTH = "border-width";
    public static final String BORDER_STYLE = "border-style";
    public static final String BORDER_COLOR = "border-color";
    public static final String Z_INDEX = "z-index";
    public static final String CURSOR = "cursor";
    public static final String TEXT_DECORATION = "text-decoration";

    public Style(String name) {
        name(name);
    }

    protected Style name(String name) {
        this.name = name;
        return this;
    }

    abstract String getName();


    String get(String attributeName) {
        return (String) attributes.get(attributeName);
    }

    protected void extending(CssClass style) {
        style.copyTo(this);
    }


    public void copyTo(Style style) {
        style.copyAttributes(attributes);
    }

    private void copyAttributes(Map attributes) {
        this.attributes.putAll(attributes);
    }

    protected String nameDefinition() {
        StringBuffer name = new StringBuffer();
        name.append(getName());
        for (Iterator iterator = siblings.iterator(); iterator.hasNext();) {
            Style sibling = (Style) iterator.next();
            name.append(", ").append(sibling.nameDefinition());
        }
        return name.toString();
    }

    public T backgroundColor(String backgroundColor) {
        return attribute(BACKGROUND_COLOR, backgroundColor);
    }

    private void sibling(Style style) {
        siblings.add(style);
    }

    public T inherits(Style parent) {
        parent.sibling(this);
        return (T) this;
    }

    public T color(String color) {
        return attribute(COLOR, color);
    }

    public T backgroundImage(String backgroundImage) {
        return attribute(BACKGROUND_IMAGE, backgroundImage);
    }

    public T backgroundRepeat(String backgroundRepeat) {
        return attribute(BACKGROUND_REPEAT, backgroundRepeat);
    }

    public T backgroundNoRepeat() {
        return backgroundRepeat("no-repeat");
    }

    public T backgroundRepeatX() {
        return backgroundRepeat("repeat-x");
    }

    public T backgroundRepeatY() {
        return backgroundRepeat("repeat-y");
    }

    public T backgroundRepeatXY() {
        return backgroundRepeat("repeat");
    }

    public T backgroundPosition(String backgroundPosition) {
        return attribute(BACKGROUND_POSITION, backgroundPosition);
    }

    public T fontFamily(String fontFamily) {
        return attribute(FONT_FAMILY, fontFamily);
    }

    public T fontWeight(String fontWeight) {
        return attribute(FONT_WEIGHT, fontWeight);
    }

    public T font(Font font) {
        font.applyTo(this);
        return (T) this;
    }

    public T fontSize(String fontSize) {
        return attribute(FONT_SIZE, fontSize);
    }

    public T lineHeight(String lineHeight) {
        return attribute(LINE_HEIGHT, lineHeight);
    }

    public T margin(String margin) {
        return attribute(MARGIN, margin);
    }

    public T border(String border) {
        return attribute(BORDER, border);
    }

    public T overflow(String overflow) {
        return attribute(OVERFLOW, overflow);
    }

    public T padding(String padding) {
        return attribute(PADDING, padding);
    }

    public T padding(Unit padding) {
        return padding(padding.css());
    }

    public T paddingTop(Unit unit) {
        return attribute(PADDING_TOP, unit.css());
    }

    public T paddingBottom(Unit unit) {
        return attribute(PADDING_BOTTOM, unit.css());
    }

    public T paddingLeft(Unit unit) {
        return attribute(PADDING_LEFT, unit.css());
    }

    public T paddingRight(Unit unit) {
        return attribute(PADDING_RIGHT, unit.css());
    }

    public T width(String width) {
        return attribute(WIDTH, width);
    }

    public T width(Unit unit) {
        return width(unit.css());
    }

    public T height(String height) {
        return attribute(HEIGHT, height);
    }

    public T height(Unit unit) {
        return height(unit.css());
    }

    public T attribute(String attributeName, String attributeValue) {
        attributes.put(attributeName, attributeValue);
        return (T) this;
    }

    public Map getAttributes() {
        return attributes;
    }

    public String css() {
        return name;
    }

    public T marginBottom(String marginBottom) {
        return attribute("margin-bottom", marginBottom);
    }

    public T marginTop(String marginTop) {
        return attribute("margin-top", marginTop);
    }

    public T marginLeft(String marginLeft) {
        return attribute("margin-left", marginLeft);
    }

    public T marginRight(String marginRight) {
        return attribute("margin-right", marginRight);
    }

    public T floating(String floating) {
        return attribute("float", floating);
    }

    public T borderColor(String color) {
        return attribute("border-color", color);
    }

    public T borderTop(String border) {
        return attribute(BORDER_TOP, border);
    }

    public T borderBottom(String border) {
        return attribute(BORDER_BOTTOM, border);
    }

    public T borderLeft(String border) {
        return attribute(BORDER_LEFT, border);
    }

    public T borderRight(String border) {
        return attribute(BORDER_RIGHT, border);
    }

    public T borderCollapsed() {
        return attribute("border-collapse", "collapse");
    }

    public T align(String alignment) {
        return attribute("text-align", alignment);
    }

    public T noMargin() {
        return margin("0px");
    }

    public T zIndex(int i){
        return attribute(Z_INDEX,Integer.toString(i));
    }

    public T cursor(String cursorType){
        return attribute(CURSOR,cursorType);
    }

    public T textDecoration(String decoration){
        return attribute(TEXT_DECORATION,decoration);
    }

    public T noPadding() {
        return padding("0px");
    }

    public void style(Widget widget) {
        widget.setStyleName(name);
    }
}
